import { type HidDeviceInfo, useHid, type UseHidOptions } from './useHid'
import { useState, useEffect } from 'react';
import { useMemoizedFn } from 'ahooks';

export interface LastConnectedDevice {
  vendorId: number
  productId: number
  usage?: number
  usagePage?: number
  lastConnectedTime: number
}

export function useHidAutoConnect(options: UseHidOptions = {}) {
  const [lastConnectedDevice, setLastConnectedDevice] = useState<LastConnectedDevice | null>(null)
  const [autoConnectAttempted, setAutoConnectAttempted] = useState(false)
  const [isAutoConnecting, setIsAutoConnecting] = useState(false)

  // Use the original useHid hook
  const hid = useHid({
    ...options,
    onDeviceConnect: async (info, device) => {
      // Save the last connected device information
      saveLastConnectedDevice(info)
      options?.onDeviceConnect?.(info, device)
    },
  })

  // Save the last connected device information
  const saveLastConnectedDevice = useMemoizedFn((device: HidDeviceInfo) => {
    const deviceInfo: LastConnectedDevice = {
      vendorId: device.vendorId,
      productId: device.productId,
      usage: device.usage,
      usagePage: device.usagePage,
      lastConnectedTime: Date.now(),
    }
    setLastConnectedDevice(deviceInfo)
    localStorage.setItem('lastConnectedHidDevice', JSON.stringify(deviceInfo))
  })

  // Load the last connected device information
  const loadLastConnectedDevice = useMemoizedFn((): LastConnectedDevice | null => {
    try {
      const saved = localStorage.getItem('lastConnectedHidDevice')
      if (saved) {
        const device = JSON.parse(saved) as LastConnectedDevice
        setLastConnectedDevice(device)
        return device
      }
    }
    catch (error) {
      console.error('Failed to load last connected device:', error)
      localStorage.removeItem('lastConnectedHidDevice')
    }
    return null
  })

  // Check if the device is connected to the system
  const isDevicePresent = useMemoizedFn(async (device: LastConnectedDevice): Promise<boolean> => {
    try {
      const devices = await navigator.hid.getDevices()
      return devices.some(d =>
        d.vendorId === device.vendorId
        && d.productId === device.productId
        && (!device.usage || d.collections.some(c => c.usage === device.usage))
        && (!device.usagePage || d.collections.some(c => c.usagePage === device.usagePage)),
      )
    }
    catch (error) {
      console.error('Failed to check device presence:', error)
      return false
    }
  })

  // Attempt to auto-connect the last device
  const tryAutoConnect = useMemoizedFn(async () => {
    if (autoConnectAttempted || isAutoConnecting) {
      return
    }

    const lastDevice = loadLastConnectedDevice()
    if (!lastDevice) {
      setAutoConnectAttempted(true)
      return
    }

    try {
      setIsAutoConnecting(true)

      // Check if the device is physically connected
      const isPresent = await isDevicePresent(lastDevice)
      if (!isPresent) {
        console.log('Last connected device not present')
        setAutoConnectAttempted(true)
        return
      }

      // Get the device instance
      const devices = await navigator.hid.getDevices()
      const device = devices.find(d =>
        d.vendorId === lastDevice.vendorId
        && d.productId === lastDevice.productId
        && (!lastDevice.usage || d.collections.some(c => c.usage === lastDevice.usage))
        && (!lastDevice.usagePage || d.collections.some(c => c.usagePage === lastDevice.usagePage)),
      )

      if (device) {
        await hid.connectDevice(device)
      }
    }
    catch (error) {
      console.error('Auto connect failed:', error)
    }
    finally {
      setIsAutoConnecting(false)
      setAutoConnectAttempted(true)
    }
  })

  // Clear the last connected device information
  const clearLastConnectedDevice = useMemoizedFn(() => {
    setLastConnectedDevice(null)
    localStorage.removeItem('lastConnectedHidDevice')
  })

  useEffect(() => {
    // Attempt to auto-connect when the component is mounted
    tryAutoConnect()
  }, [])

  return {
    ...hid,
    lastConnectedDevice,
    isAutoConnecting,
    autoConnectAttempted,
    tryAutoConnect,
    clearLastConnectedDevice,
  }
}
